package com.example.demo.config.security.rest;

import com.aliyun.oss.OSS;
import com.aliyun.oss.OSSClientBuilder;
import com.aliyuncs.DefaultAcsClient;
import com.aliyuncs.exceptions.ClientException;
import com.aliyuncs.http.MethodType;
import com.aliyuncs.http.ProtocolType;
import com.aliyuncs.profile.DefaultProfile;
import com.aliyuncs.profile.IClientProfile;
import com.aliyuncs.sts.model.v20150401.AssumeRoleRequest;
import com.aliyuncs.sts.model.v20150401.AssumeRoleResponse;
import com.example.demo.RestObjectResponse;
import com.example.demo.config.security.vo.OssTokenVO;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import java.net.URL;
import java.util.Date;
import java.util.Objects;

/**
 * 阿里云OSS STS
 *
 * @author leigq
 */
@Slf4j
@RestController
@RequestMapping("/aliyun/sts")
public class AliyunStsController {
    @GetMapping("url")
    public RestObjectResponse getUrlToken(){
        // Endpoint以杭州为例，其它Region请按实际情况填写。
        String endpoint = "http://oss-cn-hangzhou.aliyuncs.com";
// 阿里云主账号AccessKey拥有所有API的访问权限，风险很高。强烈建议您创建并使用RAM账号进行API访问或日常运维，请登录 https://ram.console.aliyun.com 创建RAM账号。

        String accessKeyId = "aa";
        String accessKeySecret = "aa";
        String bucketName = "mt23-public-lib";
        String objectName = "a.apk.doc";

// 创建OSSClient实例。
        OSS ossClient = new OSSClientBuilder().build(endpoint, accessKeyId, accessKeySecret);

// 设置URL过期时间为1小时。
        Date expiration = new Date(new Date().getTime() + 3600 * 1000);
// 生成以GET方法访问的签名URL，访客可以直接通过浏览器访问相关内容。
        URL url = ossClient.generatePresignedUrl(bucketName, objectName, expiration);

// 关闭OSSClient。
        ossClient.shutdown();
        return RestObjectResponse.ok(url.toString());
    }

    /**
     * 获取 OSS 签名授权
     *
     * @return
     * @author leigq
     * @date 2018-12-17 15:08:55
     **/
    @GetMapping("/oss/tokens")
    public RestObjectResponse getOssToken() {
        // 创建阿里云 OSS 临时token
        AssumeRoleResponse ossToken = createOssToken();
        if (Objects.isNull(ossToken)) {
            return RestObjectResponse.ok("获取 OSS 签名授权失败！");
        }
        // 阿里 OSS 配置
        AssumeRoleResponse.Credentials credentials = ossToken.getCredentials();
        // 构建 OSS token 返回给前端
        OssTokenVO ossTokenVO = OssTokenVO.builder()
                // region每个地方不一样，下面是深圳的：shenzhen
                .region("oss-cn-shenzhen")
                .accessKeyId(credentials.getAccessKeyId())
                .accessKeySecret(credentials.getAccessKeySecret())
                .securityToken(credentials.getSecurityToken())
                .expiration(credentials.getExpiration())
                // OSS bucket名称
                .bucket("leigq-bucket")
                .build();
        return RestObjectResponse.ok(ossTokenVO);
    }

    /**
     * 创建阿里云 OSS 临时token
     * @author leigq
     * @return
     */
    private AssumeRoleResponse createOssToken() {
        /*
         * 子账号的 accessKeyId、accessKeySecret、roleArn，注意：子账号需赋予 AliyunSTSAssumeRoleAccess(调用STS服务AssumeRole接口的权限)权限
         * */
        String accessKeyId = "aa";
        String accessKeySecret = "aa";
        String roleArn = "acs:ram::aa:role/uploader";

        //roleSessionName时临时Token的会话名称，自己指定用于标识你的用户，或者用于区分Token颁发给谁
        //要注意roleSessionName的长度和规则，不要有空格，只能有'-'和'_'字母和数字等字符
        String roleSessionName = "session-name";
        try {
            // 创建一个 Aliyun Acs Client, 用于发起 OpenAPI 请求
            DefaultProfile.addEndpoint("", "", "Sts", "sts.aliyuncs.com");
            IClientProfile profile = DefaultProfile.getProfile("", accessKeyId, accessKeySecret);
            DefaultAcsClient client = new DefaultAcsClient(profile);
            // 创建一个 AssumeRoleRequest 并设置请求参数
            final AssumeRoleRequest request = new AssumeRoleRequest();
            //POST请求
            request.setMethod(MethodType.POST);
            //https协议
            request.setProtocol(ProtocolType.HTTPS);
            //持续时间, 只能设置 15min - 1hr 之间
            request.setDurationSeconds(900L);
            //角色id
            request.setRoleArn(roleArn);
            //应用程序标识(自己定义)
            request.setRoleSessionName(roleSessionName);
            // 发起请求，并得到response
            AssumeRoleResponse acsResponse = client.getAcsResponse(request);
            return acsResponse;
        } catch (ClientException e) {
            log.error("创建阿里云 OSS 临时token异常", e);
        }
        return null;
    }
}